#include "Closure.h"

#include <google/protobuf/util/json_util.h>

namespace emoney {
    Closure::Closure(drogon::HttpResponsePtr respPtr, google::protobuf::Message* pReqMsg, google::protobuf::Message* pRespMsg, Done& done)
        : mDone(done), mReqMsg(pReqMsg),  mRespMsg(pRespMsg), mRespPtr(respPtr) {
        SetError(0, "");
    }

    Closure::~Closure() {
        if (mReqMsg != nullptr) {
            delete mReqMsg;
        }

        if (mRespMsg != nullptr) {
            delete mRespMsg;
        }
    }

    void Closure::Run() {
        std::string body;

        if (m_customReply.empty())
        {
            m_BaseResp.mutable_data()->PackFrom(*mRespMsg);
            if (mRespPtr->getContentType() == drogon::ContentType::CT_APPLICATION_JSON) {
                ::google::protobuf::util::JsonOptions opts;
                opts.always_print_primitive_fields = true;
                //opts.always_print_enums_as_ints = 1;
                ::google::protobuf::util::MessageToJsonString(m_BaseResp, &body, opts);
            }
            else {
                m_BaseResp.SerializeToString(&body);
            }
        }
        else
        {
            std::swap(m_customReply, body);
        }
        
        auto resp = drogon::HttpResponse::newHttpResponse();
        resp->setStatusCode(drogon::k200OK);
        mRespPtr->setBody(body);
        mDone(mRespPtr);
    }

    void Closure::SetError(int code, const char* pszErrrMsg) {
        m_BaseResp.mutable_result()->set_code(code);
        m_BaseResp.mutable_result()->set_msg(pszErrrMsg);
    }

    void Closure::SetCustomReply(const std::string& reply)
    {
        m_customReply = reply;
    }

    ClosureDone::ClosureDone(Closure* closure) : _closure(closure) {}
    ClosureDone::~ClosureDone() {
        if (_closure && !_closure->isAsync()) {
            _closure->Run();
            delete _closure;
            _closure = nullptr;
        }
    }

}
